/*
 * BootLoader.c
 *
 *  Created on: Sep 9, 2021
 *      Author: ZhangJianCe
 */
#include "BootLoader.h"


/*帧变量定义*/
frame_t frame;

/*更新程序成功标志位*/
uint8_t BootLoad_Suuccess = 0;

void Jump_Application(void)
{
	JumpApp_Handle JumpAPP = (JumpApp_Handle)(*(__IO uint32_t*)(APP_Address+4));
	uint32_t SP_Address = *(__IO uint32_t*)(APP_Address);

	/*重置SP指针*/
	__set_MSP(SP_Address);

	/*跳转到APP*/
	JumpAPP();
}



void BootLoader_Initialize(void)
{
    if (Bootload_Required() == 1)
    {
        Run_Bootloader();
    }
}

uint8_t Bootload_Required(void)
{
	uint32_t APP_Valid_Flag;
	/*读取APP有效标志位*/
	APP_Valid_Flag = *(__IO uint32_t*)(APP_Valid_Flag_Address);

	if(APP_Valid_Flag != APPLICATION_VALID)
	{
		return 1;
	}

	return 0;
}

void Run_Bootloader(void)
{
	uint8_t  ch;
    uint16_t  index;
    uint16_t  msg_length;

	while(BootLoad_Suuccess != 1)
	{
        index = 0;
        msg_length = 9;
        while (index < msg_length)
        {
        	HAL_UART_Receive(&huart1,&ch,1,0xFFFFFFFF);
            frame.buffer[index++] = ch;
            if (index == 5)
            {
                if (frame.command == WRITE_FLASH)
                {
                    msg_length += frame.data_length;
                }
            }
        }
        msg_length = ProcessBootBuffer();
        index = 0;
        while (index < msg_length)
        {
        	HAL_UART_Transmit(&huart1,&frame.buffer[index++],1,0xFFFFFFFF);
        }
	}
}

uint8_t ProcessBootBuffer(void)
{
	uint8_t  len = 0;

	switch (frame.command)
	{
	case    READ_VERSION:
		len = Get_Version_Data();
		break;
	case    ERASE_FLASH:
		len = Erase_Flash();
		break;
	case    WRITE_FLASH:
		len = Write_Flash();
		break;
	case    CALC_CHECKSUM:
		len = Calc_Checksum();
		break;
	case    Jump_APP:
		Write_APP_Valid_Flag();
		HAL_UART_DeInit(&huart1);
		Jump_Application();
		break;
	default:
		frame.command = 0xFF;
		frame.data[0] = ERROR_INVALID_COMMAND;
		len = 9;
	}
	return (len);
}

uint8_t Get_Version_Data(void)
{
	/*版本1.0*/
    frame.data[0] = 1;
    frame.data[1] = 0;

    frame.data[2] = (Flash_Max_Address&0xFF);
    frame.data[3] = ((Flash_Max_Address>>8)&0xFF);
    frame.data[4] = ((Flash_Max_Address>>16)&0xFF);
    frame.data[5] = ((Flash_Max_Address>>24)&0xFF);

    return 15;
}

uint8_t Write_Flash(void)
{
	uint8_t ret=0;
	/*临时存放要写入的双字数据*/
	uint64_t Write_Data;
	/*临时存放要写入的地址*/
	uint32_t Write_Addr = *((__IO uint32_t*)(&frame.buffer[5]));
	/*临时存放要写入的字节数*/
	uint32_t Byte_Length = frame.data_length;
	/*以上内容使用局部变量可以减少汇编后的指令数量
	 * 从而增加速度,以空间换时间*/

	/*写入前先解锁Flash*/
	 ret+=HAL_FLASH_Unlock();

    for (uint32_t  i= 0; i < Byte_Length; i+=4)
    {
    	/*从数据接收区读取写入数据*/
    	Write_Data = *((__IO uint32_t*)(&frame.data[i]));
    	/*调用HAL驱动写入Flash,每次写入一个双字，即8字节*/
    	ret+=HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,Write_Addr,Write_Data);
    	Write_Addr+=4;

    	HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
    }
	/*写入后上锁Flash*/
    ret+=HAL_FLASH_Lock();

    if(ret==0)
    {
    	frame.data[0] = COMMAND_SUCCESS;
    }
    else
    {
		frame.data[0] = WRITE_FAILD;
    }
    return (10);
}

uint8_t Erase_Flash(void)
{
	uint8_t ret=0;

	/*获取地址*/
	uint32_t Erase_Start_Addr = *((__IO uint32_t*)(&frame.buffer[5]));
	uint32_t Erase_End_Addr = Erase_Start_Addr+frame.data_length-1;

	/*获取页地址*/
	uint32_t Start_Page_Addr = Erase_Start_Addr&(0xffffffff<<Invalid_Bits);
	uint32_t End_Page_Addr = Erase_End_Addr&(0xffffffff<<Invalid_Bits);

	/*获取页跨度*/
	uint16_t Erase_Page_Number = (End_Page_Addr-Start_Page_Addr)>>Invalid_Bits;

	/*擦除前先解锁Flash*/
	 ret+=HAL_FLASH_Unlock();


	uint32_t Erase_Ret;
	FLASH_EraseInitTypeDef Erase_Config;
	Erase_Config.TypeErase = FLASH_TYPEERASE_PAGES;
	Erase_Config.Banks = FLASH_BANK_1;
	Erase_Config.NbPages = Erase_Page_Number;
	Erase_Config.PageAddress = Start_Page_Addr;

	ret+=HAL_FLASHEx_Erase(&Erase_Config,&Erase_Ret);

	/*擦除后上锁Flash*/
    ret+=HAL_FLASH_Lock();

    if(ret==0)
    {
    	frame.data[0] = COMMAND_SUCCESS;
    	HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);
    }
    else
    {
		frame.data[0] = ERASE_FAILD;
    }
    return (10);
}

uint8_t Calc_Checksum()
{
	uint8_t check_sum=0;
	/*临时存放要读取的字数据*/
	uint32_t Read_Data;
	/*临时存放要读取的地址*/
    uint32_t Read_Addr = *((__IO uint32_t*)(&frame.buffer[5]));
    for (uint32_t i = 0;i < frame.data_length; i++)
    {
    	Read_Data = *((__IO uint32_t*)(Read_Addr));
    	check_sum+=Read_Data;
    	Read_Addr++;
     }
     frame.data[0] = check_sum;

     return (10);
}


void Write_APP_Valid_Flag(void)
{
	BootLoad_Suuccess = 1;
	/*写入前先解锁Flash*/
	HAL_FLASH_Unlock();
	HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,APP_Valid_Flag_Address,APPLICATION_VALID);
	/*写入后上锁Flash*/
	HAL_FLASH_Lock();
	HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);
}


